#include "usb_comm.h"
#include "usb_dev_cdc_class.h"
#include "string.h"

static struct {
    uint32_t bitrate;
    uint8_t  format;
    uint8_t  paritytype;
    uint8_t  datatype;
} linecoding = {
    115200, /* baud rate - 115200 */
    0x00,   /* stop bits - 1 */
    0x00,   /* parity    - none */
    0x08    /* data bit  - 8 */
};


uint16_t gen_msg_acq(uint8_t req_type);
uint16_t dev_acq_msg_len;
uint8_t dev_acq_msg[DEV_CMD_MAX_SIZE];
uint8_t host_cmd_buf[HOST_CMD_MAX_SIZE];
uint16_t host_cmd_recv_cnt;
uint16_t host_cmd_len;
_Bool   host_cmd_recv_finish;

/**
 * @brief  Manage the CDC class requests
 * @param  [in] Cmd     Command code
 * @param  [in] Buf     data to be sent or received
 * @param  [in] Len     data length in bytes
 * @retval status
 */
void vcp_ctrlpare(uint32_t Cmd, uint8_t *Buf, uint32_t Len)
{
    switch (Cmd) {
        case SET_LINE_CODING:
            linecoding.bitrate = ((uint32_t)Buf[0U] | ((uint32_t)Buf[1U] << 8U) | ((uint32_t)Buf[2U] << 16U) | ((uint32_t)Buf[3U] << 24U));
            linecoding.format = Buf[4];
            linecoding.paritytype = Buf[5U];
            linecoding.datatype = Buf[6U];
            /* Set the new configuration */
            break;
        case GET_LINE_CODING:
            Buf[0U] = (uint8_t)(linecoding.bitrate);
            Buf[1U] = (uint8_t)(linecoding.bitrate >> 8U);
            Buf[2U] = (uint8_t)(linecoding.bitrate >> 16U);
            Buf[3U] = (uint8_t)(linecoding.bitrate >> 24U);
            Buf[4U] = linecoding.format;
            Buf[5U] = linecoding.paritytype;
            Buf[6U] = linecoding.datatype;
            break;

        default:
            break;
    }
}


/**
 * @brief  Data received from USB are sent to uart port
 * @param  [in] Buf     buffer to be sent to uart port
 * @param  [in] Len     data length in bytes
 * @retval None
 */
void vcp_rxdata(uint8_t *Buf, uint32_t Len)
{
    uint32_t i;
    
    memcpy(host_cmd_buf + host_cmd_recv_cnt, Buf, Len);
    host_cmd_recv_cnt += Len;
    if(host_cmd_recv_cnt <= 64)
    {
        host_cmd_len = 3 + (host_cmd_buf[0] | (host_cmd_buf[1]<<8) | (host_cmd_buf[2]));
        host_cmd_recv_finish = 0;
    }
    if(host_cmd_recv_cnt == host_cmd_len)
        host_cmd_recv_finish = 1;
    if(host_cmd_recv_finish)
    {
        dev_acq_msg_len = gen_msg_acq(host_cmd_buf[3]);

        memcpy(uart_rx_buffer + APP_Rx_ptr_in, dev_acq_msg, dev_acq_msg_len);
        APP_Rx_ptr_in += dev_acq_msg_len;

        /* To avoid buffer overflow */
        if (APP_Rx_ptr_in == APP_RX_DATA_SIZE)
            APP_Rx_ptr_in = 0U;
    }
}


uint16_t gen_msg_acq(uint8_t req_type)
{
    return 0;
}

int32_t usb_receive_firmware(void)
{
    return LL_OK;
}


int32_t usb_check_firmware(void)
{
    return LL_OK;
}


int32_t usb_write_firmware(void)
{
    return LL_OK;
}


int32_t usb_sysneedreset(void)
{
    return LL_OK;
}
